SummaryBy Steve Small
The release of JavaServer Pages (JSP) Standard Tag Library (JSTL) is a significant development for JSP/servlet developers. With an expression language (EL) and a set of four powerful, easy-to-learn standard tag libraries, JSTL is likely to soon become the dominant approach for implementing dynamic, Java-based Websites. (4,100 words; February 28, 2003)
he 1996 introduction of Java servlets made Java a reasonable choice for dynamic Webpage development. The subsequent debut of JavaServer Pages (JSP) followed by the inclusion of support for JSP tags were logical evolutionary steps toward fast, maintainable Java Webpage implementation. But the mid-2002 release of JSTL (JSP Standard Tag Library) represents perhaps the biggest step yet in speeding and simplifying the development process further.
In this article, I explain JSTL's capabilities and cover everything you need to get started with JSTL. It's assumed you have a basic understanding of Java, JSP, XML, and setting up a Web container. If you're not comfortable with these topics, you might want to browse the background references in Resources. Additional assumed knowledge is described in the XML and SQL sections below.
Installing JSTL support
For our
JSTL installation example, we use Tomcat 4.1 (although any servlet container
that supports the Servlet 2.3 and JSP 1.2 specifications should work). First, download
Tomcat and follow the setup instructions. (Note that JSTL requires a JSP 1.2 Web
container.)
Start Tomcat with tomcat4 start
and load the index.html page to
make sure Tomcat is alive and well.
Next, you'll need to install JSTL support. You can download JSTL support from the Jakarta Website then follow these steps:
common/lib
in your
Tomcat installation (although you won't need all the jar files for our
project). This makes the JSTL jar files available to any of your Web
applications.
.tld
files to the WEB-INF
directory in your Web
application.
web.xml
file and add
the following entries:
<taglib>
<taglib-uri>http://java.sun.com/jstl/fmt</taglib-uri>
<taglib-location>/WEB-INF/fmt.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/core</taglib-uri>
<taglib-location>/WEB-INF/c.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/sql</taglib-uri>
<taglib-location>/WEB-INF/sql.tld</taglib-location>
</taglib>
<taglib>
<taglib-uri>http://java.sun.com/jstl/x</taglib-uri>
<taglib-location>/WEB-INF/x.tld</taglib-location>
</taglib>
These entries let your Web application use the expression language (EL)
versions of the JSTL tag libraries. Position of these entries matters! If
you're not sure where to put them, the definitive guide to
web.xml
options and ordering is defined in the document type
definition (DTD) at: http://java.sun.com/j2ee/dtds/web-app_2_2.dtd.
.jsp
extension.
The basics
First, all JSTL pages
are also JSP pages. JSTL is just a superset of JSP functionality.
Also, all JSTL tags are valid XML. That means if you treat the context of a page outside the JSTL tags as template text (which will normally be HTML), the remaining JSTL tags must parse as valid XML. This has some important implications, most of which are good.
JSTL provides a set of four standard tag libraries (core, internationalization/format, XML, and SQL) and support for an EL. A primary design goal for JSTL and the EL was to simplify Webpage development and implementation.
In this article, we follow the JSTL specification's naming convention and refer to JSTL tags as actions. A JSTL tag corresponds to some action; calling them actions explicitly remind us that they add dynamic behavior to an otherwise static page.
The JSTL tag library comes in two versions: one lets you plug in the standard
JSP expressions you've used in the past, such as <%= . . .
%>
, and one uses a JSTL EL. I further discuss EL support in JSTL
below.
EL support
To understand the
current state of EL support in JSTL, let's examine how the relevant
specifications have been handled. The Java Specification Request (JSR) expert
group members decided, for good reasons, that an expression language
specification should be part of the JSP, not the JSTL, specification. Complete
specification of an expression language will be part of the JSP 2.0
specification. Since JSTL 1.0 was finalized before JSP 1.3, the JSTL authors had
to make an educated guess (which will probably turn out to be quite good) on an
EL support implementation for JSTL 1.0. A JSTL maintenance release will coincide
with finalization of the JSP 1.3 specification and will contain any tweaks to
the EL required for consistency with the final JSP 1.3 specification.
The bottom line is that the EL described here may change a bit in an upcoming JSTL release. However, any changes will likely be small.
The EL simply defines a powerful language for expressing simple expressions in a syntax that's easy to learn. It has the flavor of a cross between JavaScript and the better parts of Perl. EL expressions, combined with JSTL tags from the four standard tag libraries, provide a large, flexible feature set.
All EL expressions are enclosed by ${ }
. Expressions in JSTL are
always part of attribute values in JSTL tags. The expressions may be the only
part of the attribute or may be combined and embedded in string literals. JSTL
attributes may also contain simple string literals. In the following JSTL, we
show each of these cases in a c:out
action, which is an action from
the core library that spews the contents of its value
attribute to
the JSP's output:
<c:out value="${anExpression}"/>
<c:out
value="literalText${anExpression}${anotherExpression}"/>
<c:out
value="literalText"/>
The EL also defines a set of rules for coercing values in an expression to a type that corresponds to the context in which the values are used. We won't cover these rules in detail here; however, the approach is very similar to that defined in Perl. (As with most things Perl, this approach works reasonably well, but, on occasion, gives results the language happily accepts, but may not be quite what you expect.)
The EL provides support for accessing object properties and collection
elements, a set of implicit objects, and using relational, logical, and
arithmetic operators. For indexed properties, including arrays and
java.util.List
classes, elements can be accessed with syntax like
the following:
${alist[4]}
${aList[someVariable]}
Both JavaBean properties and java.util.Map
elements (which
represent a set of name/value pairs) can be accessed using one of the following
ways. In the first two expressions below, we can access a property named
aProperty
in a JavaBean or a Map
entry with the key
aProperty
. In the third expression (note I've left out the quotes),
we access an element in anObject
with a name held in the variable
aVariableContainingPropertyName
:
${anObject.aProperty}
${anObject["aPropertyName"]}
${anObject[aVariableContainingPropertyName]}
There are a number of implicit varibles defined in the EL:
pageContext
: the pageContext
object for that
Webpage
pageScope
, requestScope
,
sessionScope
, and applicationScope
: these are
Map
collections that map variable names in each of these scopes
to values
param
and paramValues
: parameters passed with
the page request; same as in JSP
header
and headerValues
: headers passed with the
page request; same as in JSP
cookie
: Map
that maps cookie names to a
particular cookie object The EL defines a full set of operators that corresponds closely to those
you're familiar with in Java. Arithmetic operators include +
,
-
, *
, /
(or div
), and
%
(or mod
). Relational operators include
==
, !=
, <
, >
,
<=
, >=
, which correspond to eq
,
ne
, lt
, gt
, le
, and
ge
, respectively. I won't elaborate on these operators because they
are all self-explanatory.
JSTL tag libraries
Now that I've
covered some basics and looked at EL syntax, I can discuss the four JSTL tag
libraries specifically. I discuss the core library most since it's the one
you'll certainly use; but I'll also cover the rest in enough detail to get you
started.
First, though, I should talk more about the JSTL tag libraries' two flavors. I mentioned above that each JSTL tag library comes in two versions: one that supports expressions in the EL and one that supports standard JSP expressions. When you import any tag library into a JSP page, you define a prefix that designates a namespace corresponding to the tags in that library.
The four standard tag libraries, with their JSTL spec-defined prefix conventions, are listed below. Note that you could define your own prefixes, but there is absolutely no good reason for this.
Four standard tag libraries
|
To use the EL core tag library in your page (you're really just giving your page visibility into the namespace defined in the library), include the following example directive at the top of your page:
<%@ taglib prefix="c" uri=http://java.sun.com/jstl/core %>
To use the tags in that core library, prefix each tag in your page with the prefix you've designated in your include statement:
<c:out value="${anExpression}"/>
The core tag library
Let's examine
the core tag library in more detail. We look at the most commonly used
functionality first.
Displaying/setting values and exception handling
The
core library's most basic tag is the c:out
tag, which displays an
EL expression's value in a page. An example expression that uses
c:out
might look like this:
We have <c:out value="${applicationScope.product.inventoryCount}"
escapeXml="true" default="0" /> of those items in
stock.
In the above, the value
attribute is the expression we send to
the page output. I've also shown the optional escapeXml
attribute,
which specifies whether XML characters (<
, >
,
&
, and .
) should convert to corresponding
character entity codes (so they show up as those characters in an HTML page),
and the default attribute, which is used if the EL can't evaluate the value or
the value evaluates to null.
Note that when EL support is fully implemented in JSP 2.0, you won't need to
use the c:out
action; you can just embed JSP expressions directly
in the page.
Another commonly used core action is c:set
, which sets a
variable in a page. You can use c:set
in two ways. The first way
sets the variable defined in the var
attribute to the value defined
in the value
attribute, as shown below:
<c:set var="customerID" value="$param:customerNumber" scope="session"
/>
The optional scope
attribute above specifies that we want to set
the variable customerID
in the session scope; if scope is not
specified, it defaults to page scope.
Another powerful usage of c:set
assigns the contents of the
c:set
tag's body to a specified variable:
<c:set var="cellContents">
<td>
<c:out
value="${myCell}"/>
</td>
</c:set>
In the above example, a c:set
action defines a variable named
cellContents
(in page scope) that holds the contents defined in the
tag's body. In this case, the body defines an HTML table cell element. The
c:out
action in the body is evaluated, and that evaluation's
results are included in the string literal in the body.
As you might expect, JSTL has made exception handling a bit easier. In
typical JSP pages, you have two approaches for handling exceptions: try/catch
blocks in scriptlet code embedded directly in the page or with a JSP
errorPage
directive that provides a nice catch-all way to handle
any possible exception on a page. JSTL offers a good alternative with the
c:catch
action, which provides an effective way to handle
exceptions with a bit more granularity without embedding Java code in your
pages. A c:catch
action might look like this:
<c:catch>
<!--. . . some set of nested
JSTL tags below which would be hit on an
exception-->
</c:catch>
The c:catch
action has an optional attribute, a variable that
references a thrown exception.
You're less likely to use the c:remove
tag. This tag has
attributes for a variable name and a scope, and removes the specified variable
from the specified scope.
Flow control
Let's move on to JSTL's flow control and
conditional tags. If you've used conditional and flow control statements in any
language, conceptually there's not much new here.
The c:if
action handles simple conditional tests. The Boolean
expression's value in the test attribute is evaluated; if true, the body's
contents are evaluated. In the action below, we also show the optional
var
attribute that stores the test results for later use in the
page (or elsewhere, if the other optional scope
attribute is
specified):
<c:if test="${status.totalVisits == 1000000}"
var="visits">
You are the millionth visitor to our
site! Congratulations!
</c:if>
Below we show JSTL's support for switching logic with c:choose
,
c:when
, and c:otherwise
. A set of c:when
actions may be included within a choose tag; if any of the expressions in the
c:when
blocks evaluate to true, the following tests in the
c:choose
action are not evaluated. If none of the tests in the
c:when
blocks evaluate to true, c:otherwise
action's
contents, if present, are evaluated:
<c:choose>
<c:when test="${item.type ==
'book'}">
...
</c:when>
<c:when test="${item.type ==
'electronics'}">
...
</c:when>
<c:when test="${item.type ==
'toy'}">
...
</c:when>
<c:otherwise>
...
</c:otherwise>
</c:choose>
The c:foreach
action provides an easy way to iterate through a
collection's elements. If you want to only iterate over part of the collection,
you can specify starting and ending indices and an increment value with the
optional begin
, end
, and step
attributes,
respectively. In the following example, we iterate through the contents of a
collection in the variable customerNames
; in each loop, the next
element is put in the variable name and evaluated in the c:forEach
action's body.
<table>
<c:forEach var="name"
items="${customerNames}">
<tr><td><c:out
value="${name}"/></td></tr>
</c:forEach>
</table>
Remember Java's StringTokenizer
class? With the
c:forTokens
action, you can obtain similar functionality in JSTL.
This fragment iterates through items in the items
String
attribute using the delimiter(s) defined in the
delims
attribute. Note that the items
attribute
doesn't need to be a string literal; it can be any valid EL expression:
<table>
<c:forTokens items="47,52,53,55,46,22,16,2" delim=","
var="dailyPrice">
<tr><td><c:out
value="${dailyPrice}"/></td></tr>
</c:forTokens>
</table>
In the following complete JSTL page, I list all passed parameters that have
been passed to the page. The param
and paramValues
implicit objects are Java Map
collections that map keys to one or
more values. In this example, we find the key for each MapEntry
in
the collection, which is the parameter name, and use the key to look up all the
parameter values associated with the key:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c"
%>
<html>
<body>
<head>
<title>Parameter
Listing
Example</title>
</head>
<br>
<b>Parameter
values passed to this page for each parameter: </b>
<table
border="2">
<c:forEach var="current"
items="${param}">
<tr>
<td>
<b><c:out
value="${current.key}"
/></b>
</td>
<c:forEach
var="aVal"
items="${paramValues[current.key]}">
<td>
<c:out
value="${aVal}"
/>
</td>
</c:forEach>
</tr>
</c:forEach>
</table>
</body>
</html>
Other actions
There are some other important core tag
library actions we need to cover. One potential problem area in Webpage
implementation relates to URL encoding. Without URL encoding, certain characters
in URLs that pass between Webpages, like spaces, can confuse Web servers. URL
encoding ensures that these special characters are replaced with characters that
are not confusing. The following example defines a URL in the variable
myUrl
, which consists of a URL and a set of parameters. The URL
action (note we refer to "action" in the JSTL sense here) ensures that all
characters are properly encoded:
<c:url value="http://acme.com/exec/register"
var="myUrl">
<c:param name="name"
value="${param.name}"/>
<c:param name="country"
value="${param.country}"/>
</c:url>
<a href='<c:out
value="${myUrl}"/>'>Register</a>
In the code above, the param
action simply defines a set of
name/value pairs.
JSP allows page designers to include other pages' content with the
<jsp:include>
directive. JSTL extends this concept with the
JSTL c:import
action. c:import
's big advantage is that
you can specify an arbitrary URL and include page content outside of your Web
application (anywhere on the World Wide Web) or within another Web application
on your server.
A set of HTTP-related tags wouldn't be complete without a way to handle HTTP
redirection. JSTL supports that with the c:redirect
action.
The internationalization tag library
In covering JSTL support for internationalization, I assume
you have a reasonable understanding of the following subjects:
Locale
class
MessageFormat
class
Read the internationalization-related references in the background section in Resources if you need more information on these topics.
I cover the internationalization tag library in two sections below. In the
first section, I cover formatting- and parsing-related actions (that roughly
correspond to classes in the java.text
package) you're likely to
use even if you're not developing fully internationalized applications. In the
second section, I cover actions more specific to internationalization.
If there's a remote possibility your application will be used outside your native country, life will be easier if you build in internationalization support from the beginning. This is true even with an implementation approach as easy to use as JSTL.
Format tag library: Format actions
If you've used the Java DateFormat
and
NumberFormat
classes, the approach used in the tags below should
look familiar, because JSTL format actions are built on top of these classes.
These Java classes generally provide a format( )
method, which
converts a Java type to a formatted String
and a parse(
)
method, which attempts to parse a String
and creates a
Java object corresponding to that String
.
The fmt:formatNumber
action has a value
attribute,
which is an EL expression or literal just like the other value
attributes we've seen, and a pattern
attribute. This attribute
mirrors patterns as defined in the NumberFormat
class. The
following action sends a formatted String
to the JSP page's output:
<fmt:formatNumber value="1000.001" pattern="#,#00.0#"/>
In this fmt:formatNumber
action, we use the type
attribute to specify that we want the formatted value formatted as a currency
value. We save the formatted result in a variable name dollars
. In
a US locale, the following would generate the string $3456.79
(note
that it appropriately rounds the value for the currency used):
<fmt:formatNumber value="3456.789" type="currency"
var="dollars"/>
Possible values for the type
attribute above include
currency
, number
, and percent
.
In this example, we go the other way—we start with a text string containing a
formatted (currency
, per the type
attribute) field in
the value
attribute and parse it to obtain a number. The result is
typically stored in a variable specified by the var
attribute.
Although this attribute is optional, you will usually use it; otherwise, the
parsed value is simply sent to the page output:
<fmt:parseNumber value="${currencyInput}" type="currency"
var="parsedNumber"/>
The fmt:formatDate
action has a value
attribute, a
format
attribute, and an attribute that refers to the format class
that handles the formatting (typically java.util.Date
):
<jsp:useBean id="now" class="java.util.Date" />
<fmt:formatDate
value="${now}" timeStyle="long"
dateStyle="long"/>
Like number formatting, JSTL also provides a mechanism to parse a string
representing a date into a Date
object:
<fmt:parseDate value="${dateInput}" pattern="MM dd, YYYY" />
Refer to the java.util.DateFormat
class for more details on how
to handle formatting and patterns.
Format tag library: Internationalization actions
A critical piece of Java localization is the
ResourceBundle
class. JSTL actions allow you to work with this
class simply. This example uses the fmt:bundle
action to obtain a
ResourceBundle
corresponding to the current Locale
and
fmt:message
actions to look up localized strings in that resource
bundle:
<fmt:bundle basename="myBundle">
<%-- Use values in myBundle
--%>
<fmt:message key="Introduction">
<fmt:param
value="${loginName}"/>
<fmt:param
value="${loginCount}"/>
</fmt:message>
<fmt:formatDate
value="${now}" var="parsedDate"/>
</fmt:bundle>
Often, the fmt:message
action simply looks up a string
corresponding to a key. In the example above, the string in the
ResourceBundle
contains placeholders into which two values are
substituted. These values are specified in the fmt:param
actions.
This is just like the approach used by the Java MessageFormat
class.
There's a similar action to specify a time zone. The time zone applies to anything evaluated in the tag's body:
<fmt:timeZone value="someTimeZone">
<!-- actions in this context
will be evaluated using
someTimeZone -->
</fmt:timeZone>
The fmt:bundle
and fmt:timeZone
actions above have
corresponding fmt:setBundle
and fmt:setTimeZone
actions. These actions add optional scope
attributes; thus, you can
use these actions to set a resource bundle or a time zone in any scope up to
application scope.
If you work with non-European locales, you'll probably have to worry about
encoding. JSTL supports encoding with the fmt:requestEncoding
action.
The SQL tag library
JSTL allows
easy database integration. It's important to note, however, that the
out-of-the-box JSTL implementation has some limitations. The main issue relates
to connection pooling. Establishing—and maintaining—a connection to a database
is resource-intensive. JSTL SQL actions result in many database connections
being established, generally, at least one per user. Therefore, JSTL SQL tags
are great for prototyping or for low-volume, Web-based applications, but aren't
suitable for large-scale applications. A scalable production application would
typically wrap database access in a layer that hides database access and handles
details like connection pooling. There are, however, approaches that allow you
to implement connection pooling and use JSTL SQL actions with a bit of custom
code (see "JSTL 1.0: What JSP Applications Need, Part 2" in Resources).
We look at some simple examples that use JSTL tags from the SQL library. If you're familiar with SQL basics, you should be able to adapt these for your own applications.
In the following snippet, we set up a connection to a database, select a set
of order items matching an order ID, and display item
attributes in
a table:
<sql:setDataSource
driver="com.cheapDrivers.jdbcDriver"
url="jdbc:cheapDrivers:."
user="guest"
password="password"
var="dataSource"
/>
<sql:query var="orderItems"
dataSource="${dataSource}">
SELECT * FROM items
WHERE order_id =
<cout value="${orderID}"/>
ORDER BY
price
</sql:query>
<table>
<c:forEach var="row"
items="${orderItems.rows}">
<tr>
<td><c:out
value="${row.itemName}"/></td>
<td><c:out
value="${row.price}"/></td>
<td><c:out
value="${row.weight}"/></td>
</tr>
</c:forEach>
</table>
In the next example, I show how JSTL supports database transactions. In the
database world, many operations involving multiple changes to tables must be all
or nothing: if a problem happens, the changes must be undone. In the example
below, the sql:update
action is wrapped in a
sql:transaction
action; if any SQL errors occur in the course of
the transaction, all operations performed in the transaction scope roll back.
The name of the sql:update
action is a bit misleading; in
addition to SQL UPDATE
, sql:update
also supports
INSERT
and DELETE
, and even SQL CREATE
.
In fact, it supports any SQL operation that doesn't produce a result. In the
following example, the sql:update
performs an UPDATE
by inserting variable values into a PreparedStatement
. In this code
fragment, we transfer money between two accounts (a classic example of something
that needs to be wrapped in a transaction):
<sql:transaction
dataSource="${dataSource}">
<sql:update>
UPDATE account
SET
account_balance =account_balance -?
WHERE accountNo = ?
<sql:param
value="${transferAmount}"/>
<sql:param
value="${sourceAccount}"/>
</sql:update>
<sql:update>
UPDATE
account
SET account_balance =account_balance +?
WHERE accountNo =
?
<sql:param value="${transferAmount}"/>
<sql:param
value="${destAccount}"/>
</sql:update>
</sql:transaction>
The XML tag library
A complete
treatment of what you can do with the standard XML tag library, in particular
Extensible Stylesheet Language Transformations Specification (XSLT)
transformations, is a good subject for another article. I cover enough to get
you started below.
XML support in JSTL conforms to the XPath specification. One of XPath's important functions is providing a clean syntax for accessing hierarchical information for which XML is famous. Perhaps the easiest way to see how everything works is to look at the way we use XML tags in a fragment from a real JSTL page:
<!-- Find and parse our XML document (somewhere on the WWW)
-->
<c:import url="http://www.cheapstuff.com/orderStatus?id=2435"
var="xml"/>
<x:parse xml="${xml}" var="doc"/>
<!-- access XML
data via XPath expressions -->
<x:out
select="$doc/name"/>
<x:out
select="$doc/shippingAddress"/>
<x:out
select="$doc/deliveryDate"/>
<!-- Set a scoped variable
-->
<x:set var="custName" scope="request"
select="$doc/name"/>
In the import and parse actions above, we load and parse a specified XML
document into a variable doc
. In each of the x:out
actions above, we access the parsed XML document's elements using an XPath
expression and send the results to the JSP page output.
The set expression above evaluates an XPath expression and puts the results into a scoped variable (in the case above, it's in request scope).
Both the x:out
and x:set
actions can throw a
JspTagException
if they don't complete successfully (most likely
because the XPath expression referred to a tag that doesn't exist). Your page,
as in all other cases, should handle these exceptions intelligently (either via
the traditional JSP errorPage
directive or with JSTL
c:catch
actions).
JSTL handles XSLT transforms easily. In the following example page, we use
the x:transform
action from the XML tag library to create a
formatted page from an XML source document using an XSLT stylesheet. The
x:transform
action's most important attributes are the
xml
and xslt
attributes. In the example below, we set
the xslt
attribute from a variable we initialize on the same page;
we set the xml
attribute in the body of the action, which is the
default for the x:transform
action.
By default, the results of the transformation are sent to the page output;
you can also save the results in a variable with the x:var
attribute:
<%@ taglib uri="http://java.sun.com/jstl/core" prefix="c" %>
<%@
taglib uri="http://java.sun.com/jstl/xml" prefix="x" %>
<c:set
var="xsltSource">
<?xml version="1.0"?>
<xsl:stylesheet
xmlns:xsl="http://www.w3.org/1999/XSL/Transform"
version="1.0">
<xsl:template
match="/">
<xsl:apply-templates/>
</xsl:template>
<xsl:template
match="music">
<html>
<head></head>
<body
marginheight="0" marginwidth="0" topmargin="0" leftmargin="0">
<table
cellpadding="0" cellspacing="0" border="1"
bgcolor="#ffffff">
<tr>
<td><STRONG>Artist</STRONG></td>
<td><STRONG>Album</STRONG></td>
<td><STRONG>Year</STRONG></td>
<td><STRONG>Genre</STRONG></td>
</tr>
<!---Set
up for loop to collect all the artist information
//-->
<!-- <xsl:for-each
select="./*[name()='artists']">
-->
<xsl:for-each
select="artists">
<tr>
<td><xsl:value-of
select="artist"/></td>
<td><xsl:value-of
select="album"/></td>
<td><xsl:value-of
select="year"/></td>
<td><xsl:value-of
select="genre"/></td>
</tr>
</xsl:for-each>
</table>
</body>
</html>
</xsl:template>
</xsl:stylesheet>
</c:set>
<x:transform xslt="${xsltSource}"
>
<music>
<artists>
<artist>Jonny
B</artist>
<album>Feedback
and
Distortion</album>
<year>2001</year>
<genre>Rock</genre>
</artists>
<artists>
<artist>Harmony's
Nieces</artist>
<album>Sappy
Pop
Ballads</album>
<year>2002</year>
<genre>Pop</genre>
</artists>
</music>
</x:transform>
You can also use the c:import
action to specify an external
source document and stylesheet, as shown in this example code snippet:
<c:import var="${xmlSource}" url="${someDocumentURL}"
/>
<c:import var="${xsltSource}" url="${anotherDocumentURL}"
/>
<x:transform xml="${xmlSource}" xslt="${xsltSource}" >
Closing remarks
If you've made it
this far, you should have a good understanding of JSTL, its four standard tag
libraries, and how it can make Webpage development easier. Now start writing
some JSTL!
Thanks to Randy Hanford for reviewing this article.
About the author
Steve Small has been
developing with Java for many years in technical leadership and development
positions for companies including Boeing, Amazon.com, and currently at PictureIQ
in Seattle, Wash. He has developed and taught off-hours Java courses for the
University of Washington since 1998.
Background references:
JSTL references:
Other online introductions to JSTL:
JavaWorld resources: